package yunjiao.javatutorials.designpatterns.combinator;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 组合解析器,基础
 *
 * @author yangyunjiao
 */
public class Combinators {
    // 零个或多个重复
    public static <T> Parser<List<T>> many(Parser<T> parser) {
        return input -> {
            List<T> results = new ArrayList<>();
            String current = input;

            while (true) {
                ParseResult<T> result = parser.parse(current);
                if (!result.success) {
                    break;
                }
                results.add(result.value);
                current = result.remaining;
            }

            return ParseResult.success(results, current);
        };
    }

    // 一个或多个重复
    public static <T> Parser<List<T>> many1(Parser<T> parser) {
        return input -> {
            ParseResult<List<T>> result = many(parser).parse(input);
            if (result.success && !result.value.isEmpty()) {
                return result;
            }
            return ParseResult.failure("Expected at least one element");
        };
    }

    // 可选解析
    public static <T> Parser<Optional<T>> optional(Parser<T> parser) {
        return input -> {
            ParseResult<T> result = parser.parse(input);
            if (result.success) {
                return ParseResult.success(Optional.of(result.value), result.remaining);
            }
            return ParseResult.success(Optional.empty(), input);
        };
    }

    // 序列解析
    public static <A, B> Parser<B> then(Parser<A> first, Parser<B> second) {
        return input -> {
            ParseResult<A> result1 = first.parse(input);
            if (!result1.success) {
                return ParseResult.failure(result1.error);
            }
            return second.parse(result1.remaining);
        };
    }

    // 忽略左边结果
    public static <A, B> Parser<B> skipL(Parser<A> left, Parser<B> right) {
        return then(left, right).map(pair -> pair);
    }

    // 忽略右边结果
    public static <A, B> Parser<A> skipR(Parser<A> left, Parser<B> right) {
        return input -> {
            ParseResult<A> result1 = left.parse(input);
            if (!result1.success) {
                return ParseResult.failure(result1.error);
            }
            ParseResult<B> result2 = right.parse(result1.remaining);
            if (!result2.success) {
                return ParseResult.failure(result2.error);
            }
            return ParseResult.success(result1.value, result2.remaining);
        };
    }

    // 分隔的列表
    public static <T, S> Parser<List<T>> sepBy(Parser<T> parser, Parser<S> separator) {
        return input -> {
            List<T> results = new ArrayList<>();
            String current = input;

            // 解析第一个元素
            ParseResult<T> firstResult = parser.parse(current);
            if (!firstResult.success) {
                return ParseResult.success(results, current);
            }
            results.add(firstResult.value);
            current = firstResult.remaining;

            // 解析后续元素
            while (true) {
                ParseResult<S> sepResult = separator.parse(current);
                if (!sepResult.success) {
                    break;
                }
                current = sepResult.remaining;

                ParseResult<T> elemResult = parser.parse(current);
                if (!elemResult.success) {
                    break;
                }
                results.add(elemResult.value);
                current = elemResult.remaining;
            }

            return ParseResult.success(results, current);
        };
    }
}
